//
// Created by superuse on 2024/11/22.
//

#include "hotkey.hpp"
#include <windows.h>
#include <tlhelp32.h>
#include <string>
#include<Psapi.h>
#include <iostream>

std::string GetProcessPath(DWORD processId) {
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId);
    if (hProcess) {
        char path[MAX_PATH];
        if (GetModuleFileNameExA(hProcess, nullptr, path, MAX_PATH)) {
            CloseHandle(hProcess);
            return std::string(path);
        }
        CloseHandle(hProcess);
    }
    return "Unknown";
}

// 回调函数，用于枚举所有窗口
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) {
    DWORD processId;
    GetWindowThreadProcessId(hwnd, &processId);

    // 获取进程路径
    std::string processPath = GetProcessPath(processId);

    // 打印窗口所属的进程路径
    std::cout << "Window hwnd: " << hwnd << " Process Path: " << processPath << std::endl;

    return TRUE;  // 继续枚举下一个窗口
}

// 检查快捷键是否被占用
std::string CheckHotkeyOccupation(UINT modifiers, UINT vk) {
    if (RegisterHotKey(nullptr, 1, modifiers, vk)) {
        // 未被占用，取消注册
        UnregisterHotKey(nullptr, 1);
        return "No process is using this hotkey.";
    } else {
        // 快捷键被占用，使用 EnumWindows 枚举所有窗口并获取进程路径
        EnumWindows(EnumWindowsProc, 0);  // 枚举所有窗口
        return "Hotkey may be used by other processes.";
    }
}



#include <exception>

#include "Hook.hpp"

Core::Core(): getMessageHookHandle(nullptr), wndProcHookHandle(nullptr), sysMsgFilterHandle(nullptr) {
    mappedFileHandle = CreateFileMapping(
        INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, sizeof(HkdHookData), reinterpret_cast<LPCSTR>(MMF_NAME));

    dllMessageId = RegisterWindowMessage(reinterpret_cast<LPCSTR>(dllMessage));
    if (!dllMessageId) {
        throw std::exception("Couldn't register the DLL message");
    }

    if (!mappedFileHandle) {
        throw std::exception("Couldn't create a memory mapped file.");
    }

    sharedData = static_cast<HkdHookData *>(MapViewOfFile(
        mappedFileHandle, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(HkdHookData)));
    if (!sharedData) {
        CloseHandle(mappedFileHandle);
        throw std::exception("Couldn't create a view of the mapped file.");
    }

    terminatingEventHandle = CreateEvent(nullptr, true, false, reinterpret_cast<LPCSTR>(TERMINATE_EVENT_NAME));
    if (GetLastError() == ERROR_ALREADY_EXISTS) {
        ResetEvent(terminatingEventHandle);
    }
}

Core::~Core() {
    UnmapViewOfFile(sharedData);
    CloseHandle(mappedFileHandle);
    CloseHandle(terminatingEventHandle);
}

void Core::removeHooks() const {
    UnhookWindowsHookEx(getMessageHookHandle);
    UnhookWindowsHookEx(wndProcHookHandle);
    UnhookWindowsHookEx(sysMsgFilterHandle);
}

void Core::setHooks() {
    getMessageHookHandle = setupHook(WH_GETMESSAGE);
    if (!getMessageHookHandle) {
        throw std::exception("Couldn't hook WM_GETMESSAGE.");
    }

    wndProcHookHandle = setupHook(WH_CALLWNDPROC);
    if (!wndProcHookHandle) {
        throw std::exception("Couldn't hook WH_CALLWNDPROC.");
    }

    sysMsgFilterHandle = setupHook(WH_SYSMSGFILTER);
    if (!sysMsgFilterHandle) {
        throw std::exception("Couldn't hook WH_SYSMSGFILTER.");
    }
}

std::wstring Core::getProcessPathByHook(const DWORD processId) {
    HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, processId);
    if (!process) {
        return {L""};
    }

    wchar_t buffer[MAX_PATH];
    DWORD written = MAX_PATH;

    QueryFullProcessImageName(process, 0, reinterpret_cast<LPSTR>(buffer), &written);
   //
    return {buffer};
}
